use std::collections::HashMap;

use crate::{
    editor::{
        Line,
        highlighter::{Annotation, AnnotationType, SyntaxHighlighter},
    },
    prelude::{LineIdx, Location},
};

#[derive(Default)]
pub struct SearchHighlighter<'a> {
    matched_word: &'a str,
    selected_match: Option<Location>,
    highlights: HashMap<LineIdx, Vec<Annotation>>,
}

impl<'a> SearchHighlighter<'a> {
    pub fn new(matched_word: &'a str, selected_match: Option<Location>) -> Self {
        Self {
            matched_word,
            selected_match,
            highlights: HashMap::new(),
        }
    }

    fn highlight_matched_words(&self, line: &Line, result: &mut Vec<Annotation>) {
        if self.matched_word.is_empty() {
            return;
        }

        // 使用grapheme_indices确保正确的字符边界处理
        let line_str = line.to_string();
        let mut start = 0;
        while let Some(pos) = line_str[start..].find(self.matched_word) {
            let actual_pos = start + pos;
            let end_pos = actual_pos + self.matched_word.len();

            // 验证结束位置是否在字符边界上
            if end_pos > line_str.len() {
                break;
            }

            // 确保结束位置是有效的字符边界
            let mut adjusted_end = end_pos;
            while adjusted_end > actual_pos && !line_str.is_char_boundary(adjusted_end) {
                adjusted_end -= 1;
            }

            result.push(Annotation {
                annotation_type: AnnotationType::Match,
                start: actual_pos,
                end: adjusted_end,
            });

            start = adjusted_end;
        }
    }

    // 邮电小问题
    fn highlight_selected_match(&self, result: &mut Vec<Annotation>) {
        if let Some(selected_match) = self.selected_match {
            if self.matched_word.is_empty() {
                return;
            }

            let start = selected_match.cell_idx;

            result.push(Annotation {
                annotation_type: AnnotationType::SelectedMatch,
                start,
                end: start.saturating_add(self.matched_word.len()),
            });
        }
    }
}

impl<'a> SyntaxHighlighter for SearchHighlighter<'a> {
    fn highlight(&mut self, idx: LineIdx, line: &Line) {
        let mut result = Vec::new();

        self.highlight_matched_words(line, &mut result);

        if let Some(selected_match) = self.selected_match {
            if selected_match.line_idx == idx {
                self.highlight_selected_match(&mut result);
            }
        }

        self.highlights.insert(idx, result);
    }

    fn get_annotations(&self, idx: LineIdx) -> Option<&Vec<Annotation>> {
        self.highlights.get(&idx)
    }
}
